using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Newtonsoft.Json;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.DataAccess.Common;
using T.FAS.Runtime.DataAccess.Kernel;
using T.FAS.Runtime.DataAccess.SPI;
using T.FAS.Runtime.Metadata.Entity.DataModel;

namespace T.FAS.Runtime.DataAccess.Engine
{
    public class SQLService: ISQLService
    {
        public event ExecuteDataAccessAction Execute;
        public event BuildDataAccessActionContext BuildContext;

        public DataSet Query(FasDBCommand fasDBCommand)
        {
            try
            {
                var db = DatabaseFactory.CreateDefaultDatabase();
                DataSet ds = default;
                IDbDataParameter[] parameters = GetDbDataParameters(fasDBCommand);
                if (parameters == null || parameters.Count() == 0)
                {
                    ds = db.GetData(fasDBCommand.ConnectionKey, fasDBCommand.SqlStatement, "defaultTableName");
                }
                else
                {
                    ds = db.GetData(fasDBCommand.ConnectionKey, fasDBCommand.SqlStatement, "defaultTableName", parameters);
                }
                return ds;
            }
            catch (Exception e)
            {
                var str = JsonConvert.SerializeObject(fasDBCommand, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
                throw new FasException(DataModelErrorCode.Error, string.Format(CommonStringClassEngine.SQLService_Query,e.Message,str), e);
            }
        }

        private IDbDataParameter GetParameter(DatabaseType databaseType, DataType dataType)
        {
            return SampleDBFactory.GetParameter(databaseType, dataType);
        }

        /// <summary>
        /// DQ参数进行参数变量替换
        /// </summary>
        /// <param name="paramList"></param>
        /// <param name="types"></param>
        /// <param name="databaseType"></param>
        /// <returns></returns>
        private IDbDataParameter[] GetDbDataParameters(FasDBCommand fasDBCommand)
        {
            if (fasDBCommand.FasParams == null || fasDBCommand.FasParams.Count == 0) return default;
            var paramColle = new List<IDbDataParameter>();
            foreach (var parm in fasDBCommand.FasParams)
            {
                IDbDataParameter par = GetParameter(fasDBCommand.DatabaseType, parm.DataType);
                par.ParameterName = "@" + parm.Code;
                par.Value = Convert(parm.Code, parm.Value, parm.DataType);
                paramColle.Add(par);
            }
            return paramColle.ToArray();
        }

        private object Convert(string paramCode, object inputVal, DataType dataType)
        {
            var typer = DataTypeToolFactory.ValidAndConvertToObject(dataType);
            if (typer == null)
                throw new FasException(DataAccessErrorCode.ValidInput.NotSupportedType, string.Format(CommonStringClassEngine.SQLService_Convert,dataType));
            else
            {
                try
                {
                    return typer.ValidAndConvertToObject(inputVal, true);
                }
                catch (Exception e)
                {
                    throw new FasException(DataAccessErrorCode.ValidInput.ValidInputError, string.Format(CommonStringClassEngine.SQLService_Convert1,paramCode,dataType,inputVal,e.Message));
                }
            }
        }
    }
}
